#ifndef KITTINGCELL_H
#define KITTINGCELL_H

#include <QtGui/QMainWindow>
#include <qtextbrowser>
#include "ui_kittingcell.h"
#include "AnimationView.h"

#include "FactoryControlSystemAgent.h"
#include "ConveyorAgent.h"
#include "KitRobotAgent.h"
#include "Table.h"
#include "InspectorAgent.h"
#include "PartRobotAgent.h"
#include "LaneAgent.h"
#include "FeederAgent.h"
#include "GantryAgent.h"
#include "NestAgent.h"
#include "CameraAgent.h"

#include "GUIGantry.h"
#include "GUIKitRobot.h"
#include "GUIPartRobot.h"
#include "GUIRoomba.h"

#include "Lock.h"

#include <vector>
#include <string>
#include <map>

class Lock;
class FeederAgent;
class GantryAgent;

class FactoryControlSystemAgent;

class KittingCell : public QMainWindow
{
	Q_OBJECT

public:
	KittingCell(QWidget *parent = 0, Qt::WFlags flags = 0);
	~KittingCell();
	void updateTracePanel();
	void filterTracePanel();
	void Testing();
	void startFactory();
	//void startAllAgents();
	void pauseFactory();
	void stopFactory();

public slots:
	void handleStartButton();
	void handlePauseButton();
	void handleStopButton();
	void handleFactorySpeedSliderMoved(int delay);

	void handleMakePresetKitButton();
	void handlePartCleanUpButton();
	void handleMakeCustomKitButton();
	//void handleMakeBadTestKitButton();
	//void handleMakeGoodTestKitButton();

	void handlePurgeButton();
	void handleFCSBreakButton();
	void handleGantryBreakButton();
	void handleGantryExplodeButton();
	void handleConveyorsBreakButton();
	void handleKitRobotBreakButton();
	void handleFeederBreakButton();
	void handleLaneBreakButton();
	void handleNestBreakButton();
	void handleCameraBreakButton();
	void handlePartRobotBreakButton();
	void handleLaneJamButton();
	void handleLanePartJumpButton();
	void handleUnJamButton();

	void handleFCSTraceDisplayCheckbox(int state);
	void handleConveyorTraceDisplayCheckbox(int state);
	void handleKitRobotTraceDisplayCheckbox(int state);
	void handleFeederTraceDisplayCheckbox(int state);
	void handleLaneTraceDisplayCheckbox(int state);
	void handleNestTraceDisplayCheckbox(int state);
	void handleCameraTraceDisplayCheckbox(int state);
	void handlePartRobotTraceDisplayCheckbox(int state);
	void handleInspectorTraceDisplayCheckbox(int state);
	void handleGantryTraceDisplayCheckbox(int state);

	void handleFeederBreakSelectComboBoxStateChanged(QString newText);
	void handleLaneBreakSelectComboBoxStateChanged(QString newText);
	void handleNestBreakSelectComboBoxStateChanged(QString newText);
	void handleCameraBreakSelectComboBoxStateChanged(QString newText);


	void timerSlot();

private:
	std::vector<std::string> *displayableMessageSenders;
	KitRecipe* generateKitRecipeFromString(QString);
	QTimer* timer;

public:
	std::map<Agent*, std::vector<string> > messages;
	std::vector<Agent*> agents;
	AnimationView* factoryScene;
	//QTextBrowser* tracePanelTextBrowser;
	std::vector<string> *tracePanelOutputs;
	//static int msDelay;
	
	// -------------------------------------------------------------------------------
	// Agents
	FactoryControlSystemAgent* FCSAgent;

	ConveyorAgent* inConveyorAgent;
	ConveyorAgent* outGoodConveyorAgent;
	ConveyorAgent* outBadConveyorAgent;

	KitRobotAgent* kitRobotAgent;

	Table* table;
	InspectorAgent* inspectorAgent;

	PartRobotAgent* partRobotAgent;
	GantryAgent* gantryAgent;


	// GUI
	QGraphicsPixmapItem *pixOpenSign;
	QGraphicsPixmapItem *pixClosedSign;

	GUIConveyor* conveyorIn;
	GUIConveyor* conveyorOutG;
	GUIConveyor* conveyorOutB;

	vector<GUIFeeder*> feeders;
	vector<GUILane*> lanes;
	vector<GUINest*> nests;
	vector<GUICamera*> cameras;

	GUIGantry *gantryGUI;
	GUIPartRobot *partRobot;
	GUIKitRobot *kitRobot;
	GUIRoomba *roomba;

struct PartSorterUnit {

	FeederAgent* feederAgent;
	
	LaneAgent* lane1Agent;
	LaneAgent* lane2Agent;

	NestAgent* nest1Agent;
	NestAgent* nest2Agent;

	CameraAgent* cameraAgent;

	PartSorterUnit(int i) {
		char buffer [10];
		std::string name;

		itoa(i, buffer, 10);

		//name = "Feeder " + *buffer;
		name = "Feeder";

		feederAgent = new FeederAgent(name);

		lane1Agent = new LaneAgent("Lane" );//+ itoa(i * 2, buffer, 10));
		lane2Agent = new LaneAgent("Lane" );//+ itoa(i * 2 + 1, buffer, 10));

		nest1Agent = new NestAgent("Nest" );//+ itoa(i * 2, buffer, 10));
		nest2Agent = new NestAgent("Nest" );//+ itoa(i * 2 + 1, buffer, 10));

		cameraAgent = new CameraAgent("Camera"  + *itoa(i, buffer, 10));

		feederAgent->setLaneTop(lane1Agent);
		feederAgent->setLaneBottom(lane2Agent);

		lane1Agent->setFeeder(feederAgent);
		lane1Agent->setNest(nest1Agent);

		lane2Agent->setFeeder(feederAgent);
		lane2Agent->setNest(nest2Agent);

		nest1Agent->setLane(lane1Agent);
		nest2Agent->setLane(lane2Agent);

		nest1Agent->setCamera(cameraAgent);
		nest2Agent->setCamera(cameraAgent);

		cameraAgent->setNest(nest1Agent);
		cameraAgent->setNest(nest2Agent);  // TYPO?? //NO IT NEEDS TWO KEEEEEP IT
	}

	void setGantry(Gantry* gantry) {
		feederAgent->setGantry(gantry);
	}

	void setPartRobot(PartRobot* partRobot) {
		nest1Agent->setPartRobot(partRobot);
		nest2Agent->setPartRobot(partRobot);
	}

	void startAgents() {
		feederAgent->start();
	
		lane1Agent->start();
		lane2Agent->start();

		nest1Agent->start();
		nest2Agent->start();

		cameraAgent->start();
	}
};

	PartSorterUnit** partSorterUnitsAgents;
	static const int numOfPartSorterUnits = 4;


	// -------------------------------------------------------------------------------

private:
	
	Lock printVectorLock;

	Ui::KittingCellClass ui;

	void testKitRobotGoodKit();

	void testKitRobotBadKit();
};

#endif // KITTINGCELL_H
